"""Deployment资源提取器模块"""

from typing import Dict, Any, Optional, List
import yaml
import logging
from src.extractors.base import Extractor

class DeploymentExtractor(Extractor):
    """
    Deployment资源提取器
    负责从Deployment资源定义中提取关键信息
    """
    
    def __init__(self, logger: Optional[logging.Logger] = None):
        """初始化Deployment提取器"""
        super().__init__(logger)
        self.resource_type = "Deployment"
    
    def extract(self, content: str, file_path: str = "") -> Dict[str, Any]:
        """
        从Deployment YAML/JSON内容中提取信息
        
        Args:
            content: YAML/JSON格式的资源内容
            file_path: 资源文件路径，可选，用于日志记录
            
        Returns:
            提取的Deployment资源信息字典
        """
        # 解析YAML/JSON内容
        resource = self.parse_content(content, file_path)
        if not resource:
            return {}
            
        # 检查是否为Deployment资源
        if resource.get("kind") != "Deployment":
            self.logger.warning(f"资源不是Deployment: {file_path}")
            return {}
            
        # 提取基本信息
        result = self._extract_basic_info(resource)
        
        # 提取选择器
        self._extract_selector(resource, result)
        
        # 提取部署策略
        self._extract_strategy(resource, result)
        
        # 提取Pod模板
        self._extract_pod_template(resource, result)
        
        # 提取状态信息
        self._extract_status(resource, result)
        
        return result
    
    def _extract_basic_info(self, resource: Dict[str, Any]) -> Dict[str, Any]:
        """
        提取基本元数据信息
        
        Args:
            resource: 解析后的资源字典
            
        Returns:
            包含基本信息的字典
        """
        metadata = resource.get("metadata", {})
        spec = resource.get("spec", {})
        
        result = {
            "kind": "Deployment",
            "name": metadata.get("name", ""),
            "namespace": metadata.get("namespace", "default"),
            "creation_timestamp": metadata.get("creationTimestamp", ""),
            "replicas": spec.get("replicas", 1)
        }
        
        # 提取标签和注解
        if "labels" in metadata:
            result["labels"] = metadata.get("labels", {})
            
        if "annotations" in metadata:
            result["annotations"] = metadata.get("annotations", {})
            
        # 提取修订历史限制
        if "revisionHistoryLimit" in spec:
            result["revision_history_limit"] = spec.get("revisionHistoryLimit")
        
        # 提取最小就绪时间
        if "minReadySeconds" in spec:
            result["min_ready_seconds"] = spec.get("minReadySeconds")
        
        # 提取进度期限秒数
        if "progressDeadlineSeconds" in spec:
            result["progress_deadline_seconds"] = spec.get("progressDeadlineSeconds")
            
        return result
    
    def _extract_selector(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取Deployment选择器
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        spec = resource.get("spec", {})
        
        # 提取选择器
        if "selector" in spec:
            selector = spec.get("selector", {})
            if "matchLabels" in selector:
                result["selector"] = selector.get("matchLabels", {})
                
            if "matchExpressions" in selector:
                match_expressions = []
                for expr in selector.get("matchExpressions", []):
                    match_expressions.append({
                        "key": expr.get("key", ""),
                        "operator": expr.get("operator", ""),
                        "values": expr.get("values", [])
                    })
                
                if not result.get("selector"):
                    result["selector"] = {}
                    
                result["selector"]["match_expressions"] = match_expressions
    
    def _extract_strategy(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取Deployment更新策略
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        spec = resource.get("spec", {})
        
        # 提取更新策略
        if "strategy" in spec:
            strategy = spec.get("strategy", {})
            result["strategy"] = {
                "type": strategy.get("type", "RollingUpdate")
            }
            
            # 如果是滚动更新，提取相关配置
            if strategy.get("type") == "RollingUpdate" and "rollingUpdate" in strategy:
                rolling_update = strategy.get("rollingUpdate", {})
                result["strategy"]["rolling_update"] = {}
                
                if "maxUnavailable" in rolling_update:
                    result["strategy"]["rolling_update"]["max_unavailable"] = rolling_update.get("maxUnavailable")
                    
                if "maxSurge" in rolling_update:
                    result["strategy"]["rolling_update"]["max_surge"] = rolling_update.get("maxSurge")
    
    def _extract_pod_template(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取Deployment Pod模板
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        spec = resource.get("spec", {})
        
        # 提取Pod模板
        pod_template = spec.get("template", {})
        if not pod_template:
            return
            
        # 提取Pod模板元数据
        template_metadata = pod_template.get("metadata", {})
        if template_metadata:
            if "labels" in template_metadata:
                result["template_labels"] = template_metadata.get("labels", {})
                
            if "annotations" in template_metadata:
                result["template_annotations"] = template_metadata.get("annotations", {})
        
        # 提取Pod规格
        pod_spec = pod_template.get("spec", {})
        if not pod_spec:
            return
            
        # 提取重启策略
        if "restartPolicy" in pod_spec:
            result["restart_policy"] = pod_spec.get("restartPolicy")
        
        # 提取服务账号
        if "serviceAccountName" in pod_spec:
            result["service_account"] = pod_spec.get("serviceAccountName")
        
        # 提取容器
        containers = pod_spec.get("containers", [])
        if containers:
            result["containers"] = self._extract_containers(containers)
            
        # 提取初始化容器
        init_containers = pod_spec.get("initContainers", [])
        if init_containers:
            result["init_containers"] = self._extract_containers(init_containers)
        
        # 提取卷
        volumes = pod_spec.get("volumes", [])
        if volumes:
            result["volumes"] = self._extract_volumes(volumes)
        
        # 提取亲和性设置
        if "affinity" in pod_spec:
            result["affinity"] = self._clean_keys(pod_spec.get("affinity", {}))
        
        # 提取容忍度设置
        if "tolerations" in pod_spec:
            tolerations = []
            for toleration in pod_spec.get("tolerations", []):
                tolerations.append(self._clean_keys(toleration))
                
            if tolerations:
                result["tolerations"] = tolerations
        
        # 提取节点选择器
        if "nodeSelector" in pod_spec:
            result["node_selector"] = pod_spec.get("nodeSelector", {})
        
        # 提取DNS策略
        if "dnsPolicy" in pod_spec:
            result["dns_policy"] = pod_spec.get("dnsPolicy")
    
    def _extract_containers(self, containers: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        提取容器信息
        
        Args:
            containers: 容器列表
            
        Returns:
            处理后的容器信息列表
        """
        result = []
        
        for container in containers:
            container_info = {
                "name": container.get("name", ""),
                "image": container.get("image", "")
            }
            
            # 提取镜像拉取策略
            if "imagePullPolicy" in container:
                container_info["image_pull_policy"] = container.get("imagePullPolicy", "")
            
            # 提取命令和参数
            if "command" in container:
                container_info["command"] = container.get("command", [])
            
            if "args" in container:
                container_info["args"] = container.get("args", [])
            
            # 提取环境变量
            if "env" in container:
                container_info["env"] = self._extract_env_vars(container.get("env", []))
            
            # 提取环境变量来源
            if "envFrom" in container:
                container_info["env_from"] = self._clean_keys(container.get("envFrom", []))
            
            # 提取资源限制
            if "resources" in container:
                container_info["resources"] = self._clean_keys(container.get("resources", {}))
            
            # 提取卷挂载
            if "volumeMounts" in container:
                container_info["volume_mounts"] = self._extract_volume_mounts(container.get("volumeMounts", []))
                
            # 提取端口
            if "ports" in container:
                container_info["ports"] = self._extract_container_ports(container.get("ports", []))
            
            # 提取探针
            if "livenessProbe" in container:
                container_info["liveness_probe"] = self._clean_keys(container.get("livenessProbe", {}))
                
            if "readinessProbe" in container:
                container_info["readiness_probe"] = self._clean_keys(container.get("readinessProbe", {}))
                
            if "startupProbe" in container:
                container_info["startup_probe"] = self._clean_keys(container.get("startupProbe", {}))
            
            result.append(container_info)
            
        return result
    
    def _extract_env_vars(self, env_vars: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        提取环境变量
        
        Args:
            env_vars: 环境变量列表
            
        Returns:
            处理后的环境变量列表
        """
        result = []
        
        for env in env_vars:
            env_info = {
                "name": env.get("name", "")
            }
            
            if "value" in env:
                env_info["value"] = env.get("value", "")
            
            if "valueFrom" in env:
                env_info["value_from"] = self._clean_keys(env.get("valueFrom", {}))
            
            result.append(env_info)
            
        return result
    
    def _extract_volume_mounts(self, mounts: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        提取卷挂载信息
        
        Args:
            mounts: 卷挂载列表
            
        Returns:
            处理后的卷挂载列表
        """
        result = []
        
        for mount in mounts:
            mount_info = {
                "name": mount.get("name", ""),
                "mount_path": mount.get("mountPath", "")
            }
            
            if "readOnly" in mount:
                mount_info["read_only"] = mount.get("readOnly", False)
            
            if "subPath" in mount:
                mount_info["sub_path"] = mount.get("subPath", "")
                
            if "subPathExpr" in mount:
                mount_info["sub_path_expr"] = mount.get("subPathExpr", "")
                
            result.append(mount_info)
            
        return result
    
    def _extract_container_ports(self, ports: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        提取容器端口信息
        
        Args:
            ports: 端口列表
            
        Returns:
            处理后的端口列表
        """
        result = []
        
        for port in ports:
            port_info = {
                "container_port": port.get("containerPort", 0)
            }
            
            if "name" in port:
                port_info["name"] = port.get("name", "")
                
            if "protocol" in port:
                port_info["protocol"] = port.get("protocol", "TCP")
                
            if "hostPort" in port:
                port_info["host_port"] = port.get("hostPort", 0)
                
            result.append(port_info)
            
        return result
    
    def _extract_volumes(self, volumes: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        提取卷信息
        
        Args:
            volumes: 卷列表
            
        Returns:
            处理后的卷列表
        """
        result = []
        
        for volume in volumes:
            volume_info = {
                "name": volume.get("name", "")
            }
            
            # 复制所有卷字段但使用snake_case
            for key, value in volume.items():
                if key != "name":
                    snake_key = self._to_snake_case(key)
                    if isinstance(value, dict):
                        volume_info[snake_key] = self._clean_keys(value)
                    else:
                        volume_info[snake_key] = value
                    
            result.append(volume_info)
            
        return result
    
    def _extract_status(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取Deployment状态信息
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        status = resource.get("status", {})
        
        if not status:
            return
            
        result["status"] = {}
        
        # 提取副本状态
        if "replicas" in status:
            result["status"]["replicas"] = status.get("replicas", 0)
            
        if "updatedReplicas" in status:
            result["status"]["updated_replicas"] = status.get("updatedReplicas", 0)
            
        if "readyReplicas" in status:
            result["status"]["ready_replicas"] = status.get("readyReplicas", 0)
            
        if "availableReplicas" in status:
            result["status"]["available_replicas"] = status.get("availableReplicas", 0)
            
        if "unavailableReplicas" in status:
            result["status"]["unavailable_replicas"] = status.get("unavailableReplicas", 0)
        
        # 提取条件
        if "conditions" in status:
            conditions = []
            for condition in status.get("conditions", []):
                conditions.append(self._clean_keys(condition))
                
            if conditions:
                result["status"]["conditions"] = conditions
        
        # 观察到的生成
        if "observedGeneration" in status:
            result["status"]["observed_generation"] = status.get("observedGeneration", 0)
            
        # 提取发布版本
        if "collisionCount" in status:
            result["status"]["collision_count"] = status.get("collisionCount", 0)
    
    def _to_snake_case(self, camel_case: str) -> str:
        """
        将驼峰命名转换为蛇形命名
        
        Args:
            camel_case: 驼峰命名的字符串
            
        Returns:
            蛇形命名的字符串
        """
        snake_case = ""
        for i, char in enumerate(camel_case):
            if char.isupper():
                if i > 0:
                    snake_case += "_"
                snake_case += char.lower()
            else:
                snake_case += char
        return snake_case
    
    def _clean_keys(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """
        递归清理字典键为蛇形命名
        
        Args:
            data: 要清理的字典
            
        Returns:
            清理后的字典
        """
        result = {}
        
        if not isinstance(data, dict):
            return data
            
        for key, value in data.items():
            new_key = self._to_snake_case(key)
            
            if isinstance(value, dict):
                result[new_key] = self._clean_keys(value)
            elif isinstance(value, list):
                result[new_key] = [
                    self._clean_keys(item) if isinstance(item, dict) else item
                    for item in value
                ]
            else:
                result[new_key] = value
                
        return result
    
    def parse_content(self, content: str, file_path: str = "") -> Dict[str, Any]:
        """
        解析YAML/JSON内容
        
        Args:
            content: YAML/JSON格式的字符串内容
            file_path: 文件路径，用于记录日志
            
        Returns:
            解析后的字典
        """
        if isinstance(content, dict):
            return content
            
        try:
            return yaml.safe_load(content) or {}
        except yaml.YAMLError as e:
            self.logger.error(f"解析YAML失败: {file_path}, 错误: {str(e)}")
            return {}